﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
using System.Collections;
using NotAClue;

namespace NotAClue.Web.Security
{
    public static class ActiveDirectoryExtensionMethods
    {
        public static List<String> GetRolesForUser(this DirectoryEntry root, string userName, string _loginProperty)
        {
            var allRoles = new List<String>();
            DirectorySearcher searcher = new DirectorySearcher(root);

            //(&(objectClass=user)(objectCategory=person)(samAcc ountName=DINCERM))"

            searcher.Filter = String.Format("(&(objectClass=user)({0}={1}))", _loginProperty, userName);
            var result = searcher.FindOne();

            if (result != null)
            {
                var user = result.GetDirectoryEntry();
                var groups = user.Properties["memberOf"];
                foreach (String item in (Array)groups.Value)
                {
                    var name = GetGroupName(item);
                    allRoles.Add(name);
                    var parents = root.GetParentGroupsRecursive(name);
                    allRoles.AddRange(parents);
                }
            }

            return allRoles.AsQueryable().Distinct().ToList();
        }

        public static List<String> GetParentGroupsRecursive(this DirectoryEntry root, String group)
        {
            var groups = new List<String>();

            DirectorySearcher searcher = new DirectorySearcher(root);

            //(&(objectClass=user)(objectCategory=person)(samAccountName=DINCERM))"

            searcher.Filter = String.Format("(&(objectClass=group)(Name={0}))", group);
            var result = searcher.FindOne();

            if (result != null)
            {
                var user = result.GetDirectoryEntry();
                var parentGroups = user.Properties["memberOf"];

                if (parentGroups != null && parentGroups.Value != null)
                {
                    if (parentGroups.Value is Array)
                    {
                        foreach (String item in (Array)parentGroups.Value)
                        {
                            var name = GetGroupName(item);
                            groups.Add(name);
                            var parents = root.GetParentGroupsRecursive(name);
                            groups.AddRange(parents);
                        }
                    }
                    else
                    {
                        var name = GetGroupName(parentGroups.Value.ToString());
                        groups.Add(name);
                        var parents = root.GetParentGroupsRecursive(name);
                        groups.AddRange(parents);
                    }
                }
            }

            return groups.AsQueryable().Distinct().ToList();
        }

        public static string GetGroupName(string entry)
        {
            // example: 
            // CN=STSCS DART Admins,CN=Users,DC=notaclue,DC=local

            var value = entry.ToList(specrator: ',')[0].Replace("CN=", "");

            return value;
        }

        //public static List<String> GetRolesForUserRecursive(this DirectoryEntry root, string userName, string _loginProperty)
        //{
        //    var allRoles = new List<String>();
        //    foreach (DirectoryEntry entry in root.Children)
        //    {
        //        if (entry.SchemaClassName.ToLower() == "group")
        //        {
        //            object members = entry.Invoke("Members", null);
        //            foreach (object member in (IEnumerable)members)
        //            {
        //                DirectoryEntry child = new DirectoryEntry(member);

        //                var property = child.GetProperty(_loginProperty);
        //                if (property == userName)
        //                {
        //                    string name = entry.GetProperty("name");
        //                    allRoles.Add(name != "" ? name : entry.Name);
        //                    // do something here to find all the child groups of the group I found here
        //                    //var childGroups = entry.GetChildGroupsRecursive();
        //                    //allRoles.AddRange(childGroups);
        //                    //var parentGroups = entry.GetParentGroupsRecursive();
        //                    //allRoles.AddRange(parentGroups);

        //                    object groups = entry.Properties["memberOf"];
        //                    var a = (IEnumerable)groups;
        //                }
        //            }
        //        }

        //        if (entry.Children != null)
        //        {
        //            var roles = entry.GetRolesForUserRecursive(userName, _loginProperty);
        //            allRoles.AddRange(roles);
        //        }
        //    }
        //    return allRoles.AsQueryable().Distinct().ToList();
        //}

        //public static List<String> GetChildGroupsRecursive(this DirectoryEntry rootGroup)
        //{
        //    var groups = new List<String>();
        //    if (rootGroup.SchemaClassName.ToLower() == "group")
        //    {
        //        object members = rootGroup.Invoke("Members", null);
        //        foreach (object member in (IEnumerable)members)
        //        {
        //            DirectoryEntry child = new DirectoryEntry(member);

        //            if (child.SchemaClassName.ToLower() == "group")
        //            {
        //                string name = child.GetProperty("name");
        //                groups.Add(name != "" ? name : child.Name);

        //                if (child.Children != null)
        //                {
        //                    var roles = child.GetChildGroupsRecursive();
        //                    groups.AddRange(roles);
        //                }
        //            }
        //        }
        //    }

        //    return groups.AsQueryable().Distinct().ToList();
        //}

        //public static List<String> GetParentGroupsRecursive(this DirectoryEntry rootGroup)
        //{
        //    var groups = new List<String>();
        //    if (rootGroup.SchemaClassName.ToLower() == "group")
        //    {
        //        object members = rootGroup.Properties["memberOf"];
        //        //object members = rootGroup.Invoke("memberOf", null);
        //        foreach (object member in (IEnumerable)members)
        //        {
        //            DirectoryEntry child = new DirectoryEntry(member);

        //            if (child.SchemaClassName.ToLower() == "group")
        //            {
        //                string name = child.GetProperty("name");
        //                groups.Add(name != "" ? name : child.Name);

        //                if (child.Children != null)
        //                {
        //                    var roles = child.GetParentGroupsRecursive();
        //                    groups.AddRange(roles);
        //                }
        //            }
        //        }
        //    }

        //    return groups.AsQueryable().Distinct().ToList();
        //}

        //public static string GetProperty(this DirectoryEntry entry, string propertyName)
        //{
        //    var property = entry.Properties[propertyName];
        //    if ((property != null) && (property.Value != null))
        //        return property.Value.ToString();

        //    return String.Empty;
        //}
    }
}
